package com.any.sckill.distributed.zookeeper.impl;

import java.util.Objects;
import java.util.concurrent.TimeUnit;

import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.imps.CuratorFrameworkState;
import org.apache.curator.framework.recipes.locks.InterProcessMutex;

import com.any.sckill.common.constants.SeckillConstants;
import com.any.sckill.distributed.zookeeper.CuratorProxy;

public class CuratorProxyImpl implements CuratorProxy {
	
	private final CuratorFramework client;
	
	private InterProcessMutex mutex = null;
	
	private String mutexNodeName = "";
	
	public CuratorProxyImpl(CuratorFramework client) {
		if (null == client) {
			this.client = null;
		} else {
			if (client.getState().compareTo(CuratorFrameworkState.STARTED) < 0) {
				client.start();
			}
			this.client = client;
		}
	}
	
	public CuratorProxyImpl configMutex(String nodeName) {
		Objects.requireNonNull(client);
		if (null == mutex) {
			synchronized(InterProcessMutex.class) {
				if (null == mutex) {
					this.mutexNodeName = nodeName;
					mutex = new InterProcessMutex(client, SeckillConstants.SECOND_KILL_ZK_LOCK_MAIN_PATH + nodeName);
				}
			}
		}
		return this;
	}

	@Override
	public InterProcessMutex getMutex() {
		Objects.requireNonNull(mutex);
		return mutex;
	}

	@Override
	public String getMutexNodeName() {
		return mutexNodeName;
	}

	@Override
	public boolean createNode(String nodeName, byte[] content) {
		Objects.requireNonNull(client);
		try {
			client.create().creatingParentsIfNeeded().forPath(SeckillConstants.SECOND_KILL_ZK_SERVICE_PATH + nodeName, content);
			return true;
		} catch (Exception e) {
			e.printStackTrace();
			return false;
		}
	}

	@Override
	public boolean setData(String nodeName, byte[] content) {
		Objects.requireNonNull(client);
		try {
			return client.setData().forPath(SeckillConstants.SECOND_KILL_ZK_SERVICE_PATH + nodeName, content).getDataLength() > 0;
		} catch (Exception e) {
			e.printStackTrace();
			return false;
		}
	}

	@Override
	public byte[] getData(String nodeName) {
		Objects.requireNonNull(client);
		try {
			return client.getData().forPath(SeckillConstants.SECOND_KILL_ZK_SERVICE_PATH + nodeName);
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}

	@Override
	public boolean deleteNode(String nodeName) {
		Objects.requireNonNull(client);
		try {
	    	client.delete().deletingChildrenIfNeeded().forPath(SeckillConstants.SECOND_KILL_ZK_SERVICE_PATH + nodeName);
			return true;
		} catch (Exception e) {
			e.printStackTrace();
			return false;
		}
	}

	@Override
	public boolean acquire(long time, TimeUnit unit) {
    	try {
			return getMutex().acquire(time, unit);
		} catch (Exception e) {
			e.printStackTrace();
			return false;
		}
	}

	@Override
	public void release() {
    	try {
			getMutex().release();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

}
